home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / ppm / ppmtogif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-19  |  22.3 KB  |  867 lines

  1. /* ppmtogif.c - read a portable pixmap and produce a GIF file
  2. **
  3. ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A
  4. ** Lempel-Zim compression based on "compress".
  5. **
  6. ** Copyright (C) 1989 by Jef Poskanzer.
  7. **
  8. ** Permission to use, copy, modify, and distribute this software and its
  9. ** documentation for any purpose and without fee is hereby granted, provided
  10. ** that the above copyright notice appear in all copies and that both that
  11. ** copyright notice and this permission notice appear in supporting
  12. ** documentation.  This software is provided "as is" without express or
  13. ** implied warranty.
  14. **
  15. ** The Graphics Interchange Format(c) is the Copyright property of
  16. ** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
  17. ** CompuServe Incorporated.
  18. */
  19.  
  20. #include "ppm.h"
  21. #include "ppmcmap.h"
  22.  
  23. #define MAXCOLORS 256
  24.  
  25. /*
  26.  * Pointer to function returning an int
  27.  */
  28. typedef int (* ifunptr)();
  29.  
  30. /*
  31.  * a code_int must be able to hold 2**BITS values of type int, and also -1
  32.  */
  33. typedef int             code_int;
  34.  
  35. #ifdef SIGNED_COMPARE_SLOW
  36. typedef unsigned long int count_int;
  37. typedef unsigned short int count_short;
  38. #else /*SIGNED_COMPARE_SLOW*/
  39. typedef long int          count_int;
  40. #endif /*SIGNED_COMPARE_SLOW*/
  41.  
  42. static int colorstobpp ARGS(( int colors ));
  43. static int GetPixel ARGS(( int x, int y ));
  44. static void BumpPixel ARGS(( void ));
  45. static int GIFNextPixel ARGS(( ifunptr getpixel ));
  46. static void GIFEncode ARGS(( FILE* fp, int GWidth, int GHeight, int GInterlace, int Background, int BitsPerPixel, int Red[], int Green[], int Blue[], ifunptr GetPixel ));
  47. static void Putword ARGS(( int w, FILE* fp ));
  48. static void compress ARGS(( int init_bits, FILE* outfile, ifunptr ReadValue ));
  49. static void output ARGS(( code_int code ));
  50. static void cl_block ARGS(( void ));
  51. static void cl_hash ARGS(( count_int hsize ));
  52. static void writeerr ARGS(( void ));
  53. static void char_init ARGS(( void ));
  54. static void char_out ARGS(( int c ));
  55. static void flush_char ARGS(( void ));
  56.  
  57. static pixel** pixels;
  58. static colorhash_table cht;
  59.  
  60. void
  61. main( argc, argv )
  62.     int argc;
  63.     char* argv[];
  64.     {
  65.     FILE* ifp;
  66.     int argn, rows, cols, colors, i, BitsPerPixel;
  67.      int mapcols, maprows;
  68.     int interlace;
  69.     pixel** mappixels;
  70.     register pixel* pP;
  71.     pixval maxval, mapmaxval;
  72.     colorhist_vector chv;
  73.     int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
  74.     char* usage = "[-interlace] [ppmfile]";
  75.  
  76.     ppm_init( &argc, argv );
  77.  
  78.     argn = 1;
  79.     interlace = 0;
  80.     mappixels = (pixel**) 0;
  81.  
  82.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  83.         {
  84.         if ( pm_keymatch( argv[argn], "-interlace", 2 ) )
  85.             interlace = 1;
  86.         else if ( pm_keymatch( argv[argn], "-nointerlace", 2 ) )
  87.             interlace = 0;
  88.             else if ( pm_keymatch( argv[argn], "-map", 2 ) )
  89.                 {
  90.                 ++argn;
  91.                 if ( argn == argc )
  92.                 pm_usage( usage );
  93.                 ifp = pm_openr( argv[argn] );
  94.                 mappixels = ppm_readppm( ifp, &mapcols, &maprows, &mapmaxval );
  95.                 pm_close( ifp );
  96.                 if ( mapcols == 0 || maprows == 0 )
  97.                 pm_error( "cannot use a null colormap" );
  98.                 }
  99.         else
  100.             pm_usage( usage );
  101.         ++argn;
  102.         }
  103.  
  104.     if ( argn < argc )
  105.     {
  106.     ifp = pm_openr( argv[argn] );
  107.     ++argn;
  108.     }
  109.     else
  110.     ifp = stdin;
  111.  
  112.     if ( argn != argc )
  113.     pm_usage( usage );
  114.  
  115.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  116.  
  117.     pm_close( ifp );
  118.  
  119.     if ( mappixels )
  120.         {
  121.         chv = ppm_computecolorhist(
  122.             mappixels, mapcols, maprows, MAXCOLORS, &colors );
  123.         if ( chv == (colorhist_vector) 0 )
  124.             pm_error( "too many colors in colormap" );
  125.         ppm_freearray( mappixels, maprows );
  126.         pm_message( "%d colors found in colormap", colors );
  127.         }
  128.         else
  129.         {
  130.         /* Figure out the colormap. */
  131.         pm_message( "computing colormap..." );
  132.         chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
  133.         if ( chv == (colorhist_vector) 0 )
  134.         pm_error(
  135.             "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
  136.         pm_message( "%d colors found", colors );
  137.         mapmaxval = maxval;
  138.         }
  139.    /* Now turn the ppm colormap into the appropriate GIF colormap. */
  140.    if ( mapmaxval > 255 )
  141.     pm_message(
  142.        "maxval is not 255 - automatically rescaling colors" );
  143.    for ( i = 0; i < colors; ++i )
  144.         {
  145.         if ( mapmaxval == 255 )
  146.             {
  147.             Red[i] = PPM_GETR( chv[i].color );
  148.             Green[i] = PPM_GETG( chv[i].color );
  149.             Blue[i] = PPM_GETB( chv[i].color );
  150.             }
  151.         else
  152.             {
  153.             Red[i] = (int) PPM_GETR( chv[i].color ) * 255 / mapmaxval;
  154.             Green[i] = (int) PPM_GETG( chv[i].color ) * 255 / mapmaxval;
  155.             Blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / mapmaxval;
  156.             }
  157.         }
  158.     BitsPerPixel = colorstobpp( colors );
  159.  
  160.     /* And make a hash table for fast lookup. */
  161.     cht = ppm_colorhisttocolorhash( chv, colors );
  162.     ppm_freecolorhist( chv );
  163.  
  164.     /* All set, let's do it. */
  165.     GIFEncode(
  166.     stdout, cols, rows, interlace, 0, BitsPerPixel,
  167.         Red, Green, Blue, GetPixel );
  168.  
  169.     exit( 0 );
  170.     }
  171.  
  172. static int
  173. colorstobpp( colors )
  174. int colors;
  175.     {
  176.     int bpp;
  177.  
  178.     if ( colors <= 2 )
  179.     bpp = 1;
  180.     else if ( colors <= 4 )
  181.     bpp = 2;
  182.     else if ( colors <= 8 )
  183.     bpp = 3;
  184.     else if ( colors <= 16 )
  185.     bpp = 4;
  186.     else if ( colors <= 32 )
  187.     bpp = 5;
  188.     else if ( colors <= 64 )
  189.     bpp = 6;
  190.     else if ( colors <= 128 )
  191.     bpp = 7;
  192.     else if ( colors <= 256 )
  193.     bpp = 8;
  194.     else
  195.     pm_error( "can't happen" );
  196.  
  197.     return bpp;
  198.     }
  199.  
  200. static int
  201. GetPixel( x, y )
  202. int x, y;
  203.     {
  204.     int color;
  205.  
  206.     color = ppm_lookupcolor( cht, &pixels[y][x] );
  207.     return color;
  208.     }
  209.  
  210.  
  211. /*****************************************************************************
  212.  *
  213.  * GIFENCODE.C    - GIF Image compression interface
  214.  *
  215.  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background,
  216.  *            BitsPerPixel, Red, Green, Blue, GetPixel )
  217.  *
  218.  *****************************************************************************/
  219.  
  220. #define TRUE 1
  221. #define FALSE 0
  222.  
  223. static int Width, Height;
  224. static int curx, cury;
  225. static long CountDown;
  226. static int Pass = 0;
  227. static int Interlace;
  228.  
  229. /*
  230.  * Bump the 'curx' and 'cury' to point to the next pixel
  231.  */
  232. static void
  233. BumpPixel()
  234. {
  235.         /*
  236.          * Bump the current X position
  237.          */
  238.         ++curx;
  239.  
  240.         /*
  241.          * If we are at the end of a scan line, set curx back to the beginning
  242.          * If we are interlaced, bump the cury to the appropriate spot,
  243.          * otherwise, just increment it.
  244.          */
  245.         if( curx == Width ) {
  246.                 curx = 0;
  247.  
  248.                 if( !Interlace )
  249.                         ++cury;
  250.                 else {
  251.                      switch( Pass ) {
  252.  
  253.                        case 0:
  254.                           cury += 8;
  255.                           if( cury >= Height ) {
  256.                                 ++Pass;
  257.                                 cury = 4;
  258.                           }
  259.                           break;
  260.  
  261.                        case 1:
  262.                           cury += 8;
  263.                           if( cury >= Height ) {
  264.                                 ++Pass;
  265.                                 cury = 2;
  266.                           }
  267.                           break;
  268.  
  269.                        case 2:
  270.                           cury += 4;
  271.                           if( cury >= Height ) {
  272.                              ++Pass;
  273.                              cury = 1;
  274.                           }
  275.                           break;
  276.  
  277.                        case 3:
  278.                           cury += 2;
  279.                           break;
  280.                         }
  281.                 }
  282.         }
  283. }
  284.  
  285. /*
  286.  * Return the next pixel from the image
  287.  */
  288. static int
  289. GIFNextPixel( getpixel )
  290. ifunptr getpixel;
  291. {
  292.         int r;
  293.  
  294.         if( CountDown == 0 )
  295.                 return EOF;
  296.  
  297.         --CountDown;
  298.  
  299.         r = ( * getpixel )( curx, cury );
  300.  
  301.         BumpPixel();
  302.  
  303.         return r;
  304. }
  305.  
  306. /* public */
  307.  
  308. static void
  309. GIFEncode( fp, GWidth, GHeight, GInterlace, Background,
  310.            BitsPerPixel, Red, Green, Blue, GetPixel )
  311.  
  312. FILE* fp;
  313. int GWidth, GHeight;
  314. int GInterlace;
  315. int Background;
  316. int BitsPerPixel;
  317. int Red[], Green[], Blue[];
  318. ifunptr GetPixel;
  319. {
  320.         int B;
  321.         int RWidth, RHeight;
  322.         int LeftOfs, TopOfs;
  323.         int Resolution;
  324.         int ColorMapSize;
  325.         int InitCodeSize;
  326.         int i;
  327.  
  328.         Interlace = GInterlace;
  329.  
  330.         ColorMapSize = 1 << BitsPerPixel;
  331.  
  332.         RWidth = Width = GWidth;
  333.         RHeight = Height = GHeight;
  334.         LeftOfs = TopOfs = 0;
  335.  
  336.         Resolution = BitsPerPixel;
  337.  
  338.         /*
  339.          * Calculate number of bits we are expecting
  340.          */
  341.         CountDown = (long)Width * (long)Height;
  342.  
  343.         /*
  344.          * Indicate which pass we are on (if interlace)
  345.          */
  346.         Pass = 0;
  347.  
  348.         /*
  349.          * The initial code size
  350.          */
  351.         if( BitsPerPixel <= 1 )
  352.                 InitCodeSize = 2;
  353.         else
  354.                 InitCodeSize = BitsPerPixel;
  355.  
  356.         /*
  357.          * Set up the current x and y position
  358.          */
  359.         curx = cury = 0;
  360.  
  361.         /*
  362.          * Write the Magic header
  363.          */
  364.         fwrite( "GIF87a", 1, 6, fp );
  365.  
  366.         /*
  367.          * Write out the screen width and height
  368.          */
  369.         Putword( RWidth, fp );
  370.         Putword( RHeight, fp );
  371.  
  372.         /*
  373.          * Indicate that there is a global colour map
  374.          */
  375.         B = 0x80;       /* Yes, there is a color map */
  376.  
  377.         /*
  378.          * OR in the resolution
  379.          */
  380.         B |= (Resolution - 1) << 5;
  381.  
  382.         /*
  383.          * OR in the Bits per Pixel
  384.          */
  385.         B |= (BitsPerPixel - 1);
  386.  
  387.         /*
  388.          * Write it out
  389.          */
  390.         fputc( B, fp );
  391.  
  392.         /*
  393.          * Write out the Background colour
  394.          */
  395.         fputc( Background, fp );
  396.  
  397.         /*
  398.          * Byte of 0's (future expansion)
  399.          */
  400.         fputc( 0, fp );
  401.  
  402.         /*
  403.          * Write out the Global Colour Map
  404.          */
  405.         for( i=0; i<ColorMapSize; ++i ) {
  406.                 fputc( Red[i], fp );
  407.                 fputc( Green[i], fp );
  408.                 fputc( Blue[i], fp );
  409.         }
  410.  
  411.         /*
  412.          * Write an Image separator
  413.          */
  414.         fputc( ',', fp );
  415.  
  416.         /*
  417.          * Write the Image header
  418.          */
  419.  
  420.         Putword( LeftOfs, fp );
  421.         Putword( TopOfs, fp );
  422.         Putword( Width, fp );
  423.         Putword( Height, fp );
  424.  
  425.         /*
  426.          * Write out whether or not the image is interlaced
  427.          */
  428.         if( Interlace )
  429.                 fputc( 0x40, fp );
  430.         else
  431.                 fputc( 0x00, fp );
  432.  
  433.         /*
  434.          * Write out the initial code size
  435.          */
  436.         fputc( InitCodeSize, fp );
  437.  
  438.         /*
  439.          * Go and actually compress the data
  440.          */
  441.         compress( InitCodeSize+1, fp, GetPixel );
  442.  
  443.         /*
  444.          * Write out a Zero-length packet (to end the series)
  445.          */
  446.         fputc( 0, fp );
  447.  
  448.         /*
  449.          * Write the GIF file terminator
  450.          */
  451.         fputc( ';', fp );
  452.  
  453.         /*
  454.          * And close the file
  455.          */
  456.         fclose( fp );
  457. }
  458.  
  459. /*
  460.  * Write out a word to the GIF file
  461.  */
  462. static void
  463. Putword( w, fp )
  464. int w;
  465. FILE* fp;
  466. {
  467.         fputc( w & 0xff, fp );
  468.         fputc( (w / 256) & 0xff, fp );
  469. }
  470.  
  471.  
  472. /***************************************************************************
  473.  *
  474.  *  GIFCOMPR.C       - GIF Image compression routines
  475.  *
  476.  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
  477.  *  David Rowley (mgardi@watdcsu.waterloo.edu)
  478.  *
  479.  ***************************************************************************/
  480.  
  481. /*
  482.  * General DEFINEs
  483.  */
  484.  
  485. #define BITS    12
  486.  
  487. #define HSIZE  5003            /* 80% occupancy */
  488.  
  489. #ifdef NO_UCHAR
  490.  typedef char   char_type;
  491. #else /*NO_UCHAR*/
  492.  typedef        unsigned char   char_type;
  493. #endif /*NO_UCHAR*/
  494.  
  495. /*
  496.  *
  497.  * GIF Image compression - modified 'compress'
  498.  *
  499.  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
  500.  *
  501.  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  502.  *              Jim McKie               (decvax!mcvax!jim)
  503.  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
  504.  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  505.  *              James A. Woods          (decvax!ihnp4!ames!jaw)
  506.  *              Joe Orost               (decvax!vax135!petsd!joe)
  507.  *
  508.  */
  509. #include <ctype.h>
  510.  
  511. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  512.  
  513. static int n_bits;                        /* number of bits/code */
  514. static int maxbits = BITS;                /* user settable max # bits/code */
  515. static code_int maxcode;                  /* maximum code, given n_bits */
  516. static code_int maxmaxcode = (code_int)1 << BITS; /* should NEVER generate this code */
  517. #ifdef COMPATIBLE               /* But wrong! */
  518. # define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
  519. #else /*COMPATIBLE*/
  520. # define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
  521. #endif /*COMPATIBLE*/
  522.  
  523. static count_int htab [HSIZE];
  524. static unsigned short codetab [HSIZE];
  525. #define HashTabOf(i)       htab[i]
  526. #define CodeTabOf(i)    codetab[i]
  527.  
  528. static code_int hsize = HSIZE;                 /* for dynamic table sizing */
  529.  
  530. /*
  531.  * To save much memory, we overlay the table used by compress() with those
  532.  * used by decompress().  The tab_prefix table is the same size and type
  533.  * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
  534.  * get this from the beginning of htab.  The output stack uses the rest
  535.  * of htab, and contains characters.  There is plenty of room for any
  536.  * possible stack (stack used to be 8000 characters).
  537.  */
  538.  
  539. #define tab_prefixof(i) CodeTabOf(i)
  540. #define tab_suffixof(i)        ((char_type*)(htab))[i]
  541. #define de_stack               ((char_type*)&tab_suffixof((code_int)1<<BITS))
  542.  
  543. static code_int free_ent = 0;                  /* first unused entry */
  544.  
  545. /*
  546.  * block compression parameters -- after all codes are used up,
  547.  * and compression rate changes, start over.
  548.  */
  549. static int clear_flg = 0;
  550.  
  551. static int offset;
  552. static long int in_count = 1;            /* length of input */
  553. static long int out_count = 0;           /* # of codes output (for debugging) */
  554.  
  555. /*
  556.  * compress stdin to stdout
  557.  *
  558.  * Algorithm:  use open addressing double hashing (no chaining) on the
  559.  * prefix code / next character combination.  We do a variant of Knuth's
  560.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  561.  * secondary probe.  Here, the modular division first probe is gives way
  562.  * to a faster exclusive-or manipulation.  Also do block compression with
  563.  * an adaptive reset, whereby the code table is cleared when the compression
  564.  * ratio decreases, but after the table fills.  The variable-length output
  565.  * codes are re-sized at this point, and a special CLEAR code is generated
  566.  * for the decompressor.  Late addition:  construct the table according to
  567.  * file size for noticeable speed improvement on small files.  Please direct
  568.  * questions about this implementation to ames!jaw.
  569.  */
  570.  
  571. static int g_init_bits;
  572. static FILE* g_outfile;
  573.  
  574. static int ClearCode;
  575. static int EOFCode;
  576.  
  577. static void
  578. compress( init_bits, outfile, ReadValue )
  579. int init_bits;
  580. FILE* outfile;
  581. ifunptr ReadValue;
  582. {
  583.     register long fcode;
  584.     register code_int i /* = 0 */;
  585.     register int c;
  586.     register code_int ent;
  587.     register code_int disp;
  588.     register code_int hsize_reg;
  589.     register int hshift;
  590.  
  591.     /*
  592.      * Set up the globals:  g_init_bits - initial number of bits
  593.      *                      g_outfile   - pointer to output file
  594.      */
  595.     g_init_bits = init_bits;
  596.     g_outfile = outfile;
  597.  
  598.     /*
  599.      * Set up the necessary values
  600.      */
  601.     offset = 0;
  602.     out_count = 0;
  603.     clear_flg = 0;
  604.     in_count = 1;
  605.     maxcode = MAXCODE(n_bits = g_init_bits);
  606.  
  607.     ClearCode = (1 << (init_bits - 1));
  608.     EOFCode = ClearCode + 1;
  609.     free_ent = ClearCode + 2;
  610.  
  611.     char_init();
  612.  
  613.     ent = GIFNextPixel( ReadValue );
  614.  
  615.     hshift = 0;
  616.     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
  617.         ++hshift;
  618.     hshift = 8 - hshift;                /* set hash code range bound */
  619.  
  620.     hsize_reg = hsize;
  621.     cl_hash( (count_int) hsize_reg);            /* clear hash table */
  622.  
  623.     output( (code_int)ClearCode );
  624.  
  625. #ifdef SIGNED_COMPARE_SLOW
  626.     while ( (c = GIFNextPixel( ReadValue )) != (unsigned) EOF ) {
  627. #else /*SIGNED_COMPARE_SLOW*/
  628.     while ( (c = GIFNextPixel( ReadValue )) != EOF ) {    /* } */
  629. #endif /*SIGNED_COMPARE_SLOW*/
  630.  
  631.         ++in_count;
  632.  
  633.         fcode = (long) (((long) c << maxbits) + ent);
  634.         i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
  635.  
  636.         if ( HashTabOf (i) == fcode ) {
  637.             ent = CodeTabOf (i);
  638.             continue;
  639.         } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
  640.             goto nomatch;
  641.         disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
  642.         if ( i == 0 )
  643.             disp = 1;
  644. probe:
  645.         if ( (i -= disp) < 0 )
  646.             i += hsize_reg;
  647.  
  648.         if ( HashTabOf (i) == fcode ) {
  649.             ent = CodeTabOf (i);
  650.             continue;
  651.         }
  652.         if ( (long)HashTabOf (i) > 0 )
  653.             goto probe;
  654. nomatch:
  655.         output ( (code_int) ent );
  656.         ++out_count;
  657.         ent = c;
  658. #ifdef SIGNED_COMPARE_SLOW
  659.         if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
  660. #else /*SIGNED_COMPARE_SLOW*/
  661.         if ( free_ent < maxmaxcode ) {    /* } */
  662. #endif /*SIGNED_COMPARE_SLOW*/
  663.             CodeTabOf (i) = free_ent++; /* code -> hashtable */
  664.             HashTabOf (i) = fcode;
  665.         } else
  666.                 cl_block();
  667.     }
  668.     /*
  669.      * Put out the final code.
  670.      */
  671.     output( (code_int)ent );
  672.     ++out_count;
  673.     output( (code_int) EOFCode );
  674. }
  675.  
  676. /*****************************************************************
  677.  * TAG( output )
  678.  *
  679.  * Output the given code.
  680.  * Inputs:
  681.  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  682.  *              that n_bits =< (long)wordsize - 1.
  683.  * Outputs:
  684.  *      Outputs code to the file.
  685.  * Assumptions:
  686.  *      Chars are 8 bits long.
  687.  * Algorithm:
  688.  *      Maintain a BITS character long buffer (so that 8 codes will
  689.  * fit in it exactly).  Use the VAX insv instruction to insert each
  690.  * code in turn.  When the buffer fills up empty it and start over.
  691.  */
  692.  
  693. static unsigned long cur_accum = 0;
  694. static int cur_bits = 0;
  695.  
  696. static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  697.                                   0x001F, 0x003F, 0x007F, 0x00FF,
  698.                                   0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  699.                                   0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
  700.  
  701. static void
  702. output( code )
  703. code_int  code;
  704. {
  705.     cur_accum &= masks[ cur_bits ];
  706.  
  707.     if( cur_bits > 0 )
  708.         cur_accum |= ((long)code << cur_bits);
  709.     else
  710.         cur_accum = code;
  711.  
  712.     cur_bits += n_bits;
  713.  
  714.     while( cur_bits >= 8 ) {
  715.         char_out( (unsigned int)(cur_accum & 0xff) );
  716.         cur_accum >>= 8;
  717.         cur_bits -= 8;
  718.     }
  719.  
  720.     /*
  721.      * If the next entry is going to be too big for the code size,
  722.      * then increase it, if possible.
  723.      */
  724.    if ( free_ent > maxcode || clear_flg ) {
  725.  
  726.             if( clear_flg ) {
  727.  
  728.                 maxcode = MAXCODE (n_bits = g_init_bits);
  729.                 clear_flg = 0;
  730.  
  731.             } else {
  732.  
  733.                 ++n_bits;
  734.                 if ( n_bits == maxbits )
  735.                     maxcode = maxmaxcode;
  736.                 else
  737.                     maxcode = MAXCODE(n_bits);
  738.             }
  739.         }
  740.  
  741.     if( code == EOFCode ) {
  742.         /*
  743.          * At EOF, write the rest of the buffer.
  744.          */
  745.         while( cur_bits > 0 ) {
  746.                 char_out( (unsigned int)(cur_accum & 0xff) );
  747.                 cur_accum >>= 8;
  748.                 cur_bits -= 8;
  749.         }
  750.  
  751.         flush_char();
  752.  
  753.         fflush( g_outfile );
  754.  
  755.         if( ferror( g_outfile ) )
  756.                 writeerr();
  757.     }
  758. }
  759.  
  760. /*
  761.  * Clear out the hash table
  762.  */
  763. static void
  764. cl_block ()             /* table clear for block compress */
  765. {
  766.  
  767.         cl_hash ( (count_int) hsize );
  768.         free_ent = ClearCode + 2;
  769.         clear_flg = 1;
  770.  
  771.         output( (code_int)ClearCode );
  772. }
  773.  
  774. static void
  775. cl_hash(hsize)          /* reset code table */
  776. register count_int hsize;
  777. {
  778.  
  779.         register count_int *htab_p = htab+hsize;
  780.  
  781.         register long i;
  782.         register long m1 = -1;
  783.  
  784.         i = hsize - 16;
  785.         do {                            /* might use Sys V memset(3) here */
  786.                 *(htab_p-16) = m1;
  787.                 *(htab_p-15) = m1;
  788.                 *(htab_p-14) = m1;
  789.                 *(htab_p-13) = m1;
  790.                 *(htab_p-12) = m1;
  791.                 *(htab_p-11) = m1;
  792.                 *(htab_p-10) = m1;
  793.                 *(htab_p-9) = m1;
  794.                 *(htab_p-8) = m1;
  795.                 *(htab_p-7) = m1;
  796.                 *(htab_p-6) = m1;
  797.                 *(htab_p-5) = m1;
  798.                 *(htab_p-4) = m1;
  799.                 *(htab_p-3) = m1;
  800.                 *(htab_p-2) = m1;
  801.                 *(htab_p-1) = m1;
  802.                 htab_p -= 16;
  803.         } while ((i -= 16) >= 0);
  804.  
  805.         for ( i += 16; i > 0; --i )
  806.                 *--htab_p = m1;
  807. }
  808.  
  809. static void
  810. writeerr()
  811. {
  812.         pm_error( "error writing output file" );
  813. }
  814.  
  815. /******************************************************************************
  816.  *
  817.  * GIF Specific routines
  818.  *
  819.  ******************************************************************************/
  820.  
  821. /*
  822.  * Number of characters so far in this 'packet'
  823.  */
  824. static int a_count;
  825.  
  826. /*
  827.  * Set up the 'byte output' routine
  828.  */
  829. static void
  830. char_init()
  831. {
  832.         a_count = 0;
  833. }
  834.  
  835. /*
  836.  * Define the storage for the packet accumulator
  837.  */
  838. static char accum[ 256 ];
  839.  
  840. /*
  841.  * Add a character to the end of the current packet, and if it is 254
  842.  * characters, flush the packet to disk.
  843.  */
  844. static void
  845. char_out( c )
  846. int c;
  847. {
  848.         accum[ a_count++ ] = c;
  849.         if( a_count >= 254 )
  850.                 flush_char();
  851. }
  852.  
  853. /*
  854.  * Flush the packet to disk, and reset the accumulator
  855.  */
  856. static void
  857. flush_char()
  858. {
  859.         if( a_count > 0 ) {
  860.                 fputc( a_count, g_outfile );
  861.                 fwrite( accum, 1, a_count, g_outfile );
  862.                 a_count = 0;
  863.         }
  864. }
  865.  
  866. /* The End */
  867.